/*
 * @Author: nice
 * @Date: 2025-11-10 11:14:32
 * @LastEditTime: 2025-11-10 16:02:54
 * @LastEditors: nice
 * @Description: 完善后的WebRTC信令服务器（支持多观众）
 */
const express = require('express');
const https = require('https');
const { Server } = require('socket.io');
const fs = require('fs');
const path = require('path');
const os = require('os'); // 提前引入os模块

const app = express();

// 证书加载错误处理
let options;
try {
  options = {
    key: fs.readFileSync(path.join(__dirname, 'cert/server.key')),
    cert: fs.readFileSync(path.join(__dirname, 'cert/server.crt'))
  };
} catch (err) {
  console.error('证书文件加载失败:', err.message);
  console.error('请确保cert目录下存在server.key和server.crt文件');
  process.exit(1);
}

const server = https.createServer(options, app);

// 跨域配置优化（保留局域网需求同时增加安全性提示）
const io = new Server(server, {
  cors: {
    origin: "*", // 生产环境请替换为具体域名
    methods: ["GET", "POST"],
    transports: ['polling', 'websocket']
  }
});

// 状态管理（移除冗余的viewerId，统一用viewers集合）
let broadcaster = null; // 主播的socket ID
const viewers = new Set(); // 观众的socket ID集合

// 信令消息处理
io.on('connection', (socket) => {
  console.log('新连接：', socket.id);

  // 主播注册
  socket.on('broadcaster', () => {
    if (broadcaster) {
      // 已有主播时拒绝新主播注册
      socket.emit('error', '已有主播正在直播');
      return;
    }
    broadcaster = socket.id;
    socket.emit('broadcaster-ready');
    console.log('主播已连接：', broadcaster);
  });

  // 观众注册（合并request-connect逻辑，统一用viewer事件）
  socket.on('viewer', () => {
    if (!broadcaster) {
      socket.emit('error', '主播未连接');
      return;
    }
    // 避免重复添加观众
    if (viewers.has(socket.id)) {
      return;
    }
    viewers.add(socket.id);
    // 通知观众主播ID
    socket.emit('broadcaster-id', broadcaster);
    // 通知主播有新观众加入
    io.to(broadcaster).emit('viewer-connected', socket.id);
    socket.emit('viewer-ready');
    console.log('观众已连接：', socket.id, '当前观众数：', viewers.size);
  });

  // 转发WebRTC信令（支持多观众）
  socket.on('signal', (data) => {
    const { target, ...payload } = data;
    if (!target) {
      socket.emit('error', '信令缺少目标ID');
      return;
    }

    // 验证目标是否存在
    if (!io.sockets.sockets.has(target)) {
      socket.emit('error', `目标客户端不存在: ${target}`);
      console.error('信令转发失败，目标不存在:', target);
      return;
    }

    // 通用转发逻辑
    io.to(target).emit('signal', {
      from: socket.id,
      ...payload
    });

    // 日志优化
    if (socket.id === broadcaster && viewers.has(target)) {
      console.log(`转发信令: 主播 → 观众(${target})`);
    } else if (viewers.has(socket.id) && target === broadcaster) {
      console.log(`转发信令: 观众(${socket.id}) → 主播`);
    } else {
      console.log(`转发信令: ${socket.id} → ${target}`);
    }
  });

  // 断开连接处理
  socket.on('disconnect', () => {
    console.log('连接断开：', socket.id);
    
    if (socket.id === broadcaster) {
      // 主播断开
      broadcaster = null;
      // 通知所有观众主播已断开
      viewers.forEach(viewer => {
        io.to(viewer).emit('broadcaster-disconnected');
      });
      viewers.clear();
      console.log('主播已断开，观众连接已清空');
    } else if (viewers.has(socket.id)) {
      // 观众断开
      viewers.delete(socket.id);
      // 通知主播该观众已离开
      if (broadcaster) {
        io.to(broadcaster).emit('viewer-disconnected', socket.id);
      }
      console.log('观众已断开：', socket.id, '剩余观众数：', viewers.size);
    }
  });

  // 错误处理
  socket.on('error', (err) => {
    console.error('客户端错误：', socket.id, err.message);
  });
});

// 提供静态页面
app.use(express.static(path.join(__dirname, 'public')));

// 路由配置
app.get('/client', (req, res) => {
  res.sendFile(path.join(__dirname, 'public', 'client.html'));
});

app.get('/broadcaster', (req, res) => {
  res.sendFile(path.join(__dirname, 'public', 'broadcaster.html'));
});

// 启动服务
const PORT = process.env.PORT || 3001;
server.listen(PORT, '0.0.0.0', () => {
  // 获取局域网IP
  let localIp = 'localhost';
  const interfaces = os.networkInterfaces();
  for (const devName in interfaces) {
    const iface = interfaces[devName];
    for (const alias of iface) {
      if (alias.family === 'IPv4' && !alias.internal && alias.address.startsWith('10.105.')) {
        localIp = alias.address;
        break;
      }
    }
  }
  console.log(`服务启动成功！监听端口：${PORT}`);
  console.log(`Mac主播页：https://${localIp}:${PORT}/broadcaster`);
  console.log(`Windows客户端链接：https://${localIp}:${PORT}/client`);
});